﻿using Admin.Application.Const;
using Admin.Application.DynamicApi.System.Dict.Dto;
using Admin.Database.Enums;
using Admin.Database.Model;
using Framework.Core;
using Framework.Core.CustomException;
using Framework.DI;
using Framework.DynamicApiController;
using Framework.SqlSugar;
using Framework.SqlSugar.Repository;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Admin.Application.DynamicApi.System.Dict
{
	/// <summary>
	///系统字典值服务 🧩
	/// </summary>
	//[Service]
	public class SysDictDataService: ISelfTransientAutoInject
	{
		private readonly SqlSugarRepository<SysDictData> _sysDictDataRep;
		private readonly CacheHelp _sysCacheService;
		private readonly UserManager _userManager;
		public readonly ISugarQueryable<SysDictData> VSysDictData;

		public SysDictDataService(SqlSugarRepository<SysDictData> sysDictDataRep,
			CacheHelp sysCacheService,UserManager userManager)
        {
			_userManager = userManager;
			_sysDictDataRep = sysDictDataRep;
			_sysCacheService = sysCacheService;
			VSysDictData = _sysDictDataRep.AsQueryable();
		}

		/// <summary>
		/// 获取字典值分页列表 🔖
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[DisplayName("获取字典值分页列表")]
		public async Task<SqlSugarPagedList<SysDictData>> Page(PageDictDataInput input)
		{
			return await _sysDictDataRep.AsQueryable()
				.Where(u => u.DictTypeId == input.DictTypeId)
				.WhereIF(!string.IsNullOrEmpty(input.Code?.Trim()), u => u.Code.Contains(input.Code))
				.WhereIF(!string.IsNullOrEmpty(input.Label?.Trim()), u => u.Label.Contains(input.Label))
				.OrderBy(u => new { u.OrderNo, u.Code })
				.ToPagedListAsync(input.Page, input.PageSize);
		}

		/// <summary>
		/// 获取字典值列表 🔖
		/// </summary>
		/// <returns></returns>
		[DisplayName("获取字典值列表")]
		public async Task<List<SysDictData>> GetList([FromQuery] GetDataDictDataInput input)
		{
			return await GetDictDataListByDictTypeId(input.DictTypeId);
		}

		/// <summary>
		/// 增加字典值 🔖
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[HttpPost]
		[DisplayName("增加字典值")]
		public async Task AddDictData(AddDictDataInput input)
		{
			var isExist = await _sysDictDataRep.AsQueryable().AnyAsync(u => u.Value == input.Value && u.DictTypeId == input.DictTypeId);
			if (isExist) throw new CustomException("字典值已存在");

			var dictType = await _sysDictDataRep.Change<SysDictType>().GetByIdAsync(input.DictTypeId);

			Remove(dictType);

			dynamic dictData = input.Adapt<SysDictData>();
			await _sysDictDataRep.Context.Insertable(dictData).ExecuteCommandAsync();
		}

		/// <summary>
		/// 更新字典值 🔖
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[UnitOfWork]
		[HttpPost]
		[DisplayName("更新字典值")]
		public async Task UpdateDictData(UpdateDictDataInput input)
		{
			var isExist = await _sysDictDataRep.AsQueryable().AnyAsync(u => u.Id == input.Id);
			if (!isExist) throw new CustomException("字典值不存在");

			isExist = await _sysDictDataRep.AsQueryable().AnyAsync(u => u.Value == input.Value && u.DictTypeId == input.DictTypeId && u.Id != input.Id);
			if (isExist) throw new CustomException("字典值已存在");

			var dictType = await _sysDictDataRep.Change<SysDictType>().GetByIdAsync(input.DictTypeId);

			Remove(dictType);
			dynamic dictData = input.Adapt<SysDictData>();
			await _sysDictDataRep.Context.Updateable(dictData).ExecuteCommandAsync();
		}

		/// <summary>
		/// 删除字典值 🔖
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[UnitOfWork]
		[HttpPost]
		[DisplayName("删除字典值")]
		public async Task DeleteDictData(DeleteDictDataInput input)
		{
			var dictData = await _sysDictDataRep.AsQueryable().FirstAsync(u => u.Id == input.Id) ?? throw new CustomException("字典值不存在");

			var dictType = await _sysDictDataRep.Change<SysDictType>().GetByIdAsync(dictData.DictTypeId);

			Remove(dictType);
			dynamic entity = input.Adapt<SysDictData>();
			await _sysDictDataRep.Context.Deleteable(entity).ExecuteCommandAsync();
		}

		/// <summary>
		/// 获取字典值详情 🔖
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[DisplayName("获取字典值详情")]
		public async Task<SysDictData> GetDetail([FromQuery] DictDataInput input)
		{
			return (await _sysDictDataRep.AsQueryable().FirstAsync(u => u.Id == input.Id))?.Adapt<SysDictData>();
		}

		/// <summary>
		/// 修改字典值状态 🔖
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[UnitOfWork]
		[DisplayName("修改字典值状态")]
		public async Task SetStatus(DictDataInput input)
		{
			var dictData = await _sysDictDataRep.AsQueryable().FirstAsync(u => u.Id == input.Id) ?? throw new CustomException("字典值不存在");

			var dictType = await _sysDictDataRep.Change<SysDictType>().GetByIdAsync(dictData.DictTypeId);

			Remove(dictType);

			dictData.Status = input.Status;
			dynamic entity = input.Adapt<SysDictData>();
			await _sysDictDataRep.Context.Updateable(entity).ExecuteCommandAsync();
		}

		/// <summary>
		/// 根据字典类型Id获取字典值集合
		/// </summary>
		/// <param name="dictTypeId"></param>
		/// <returns></returns>
		[NonAction]
		public async Task<List<SysDictData>> GetDictDataListByDictTypeId(long dictTypeId)
		{
			return await GetDataListByIdOrCode(dictTypeId, null);
		}

		/// <summary>
		/// 根据字典类型编码获取字典值集合 🔖
		/// </summary>
		/// <param name="code"></param>
		/// <returns></returns>
		[DisplayName("根据字典类型编码获取字典值集合")]
		public async Task<List<SysDictData>> GetDataList(string code)
		{
			return await GetDataListByIdOrCode(null, code);
		}

		/// <summary>
		/// 获取字典值集合 🔖
		/// </summary>
		/// <param name="typeId"></param>
		/// <param name="code"></param>
		/// <returns></returns>
		[NonAction]
		public async Task<List<SysDictData>> GetDataListByIdOrCode(long? typeId, string code)
		{
			if (string.IsNullOrWhiteSpace(code) && typeId == null ||
				!string.IsNullOrWhiteSpace(code) && typeId != null)
				throw new CustomException("获取字典值集合入参有误");

			var dictType = await _sysDictDataRep.Change<SysDictType>().AsQueryable()
				.WhereIF(!string.IsNullOrWhiteSpace(code), u => u.Code == code)
				.WhereIF(typeId != null, u => u.Id == typeId)
				.FirstAsync();
			if (dictType == null) return null;

			string dicKey = $"{CacheConst.KeyTenantDict}{_userManager}:{dictType?.Code}";
			var dictDataList = _sysCacheService.Get<List<SysDictData>>(dicKey);
			if (dictDataList == null)
			{
				ISugarQueryable<SysDictData> sysDictData = _sysDictDataRep.AsQueryable();
				sysDictData = _sysDictDataRep.AsQueryable().Select<SysDictData>();

				dictDataList = await sysDictData.InnerJoin<SysDictType>((u, a) => u.DictTypeId == a.Id)
					.Where(u => u.DictTypeId == dictType.Id)
					.Select((u, a) => new SysDictData
					{
						Status = u.Status == StatusEnum.Enable && a.Status == StatusEnum.Enable ? StatusEnum.Enable : StatusEnum.Disable,
					}, true)
					.OrderBy(u => new { u.OrderNo, u.Value, u.Code })
					.ToListAsync();
				_sysCacheService.Set(dicKey, dictDataList);
			}
			return dictDataList;
		}

		/// <summary>
		/// 根据查询条件获取字典值集合 🔖
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[DisplayName("根据查询条件获取字典值集合")]
		public async Task<List<SysDictData>> GetDataList([FromQuery] QueryDictDataInput input)
		{
			var dataList = await GetDataList(input.Value);
			if (input.Status.HasValue) return dataList.Where(u => u.Status == (StatusEnum)input.Status.Value).ToList();
			return dataList;
		}

		/// <summary>
		/// 根据字典类型Id删除字典值
		/// </summary>
		/// <param name="dictTypeId"></param>
		/// <returns></returns>
		[NonAction]
		public async Task DeleteDictData(long dictTypeId)
		{
			var dictType = await _sysDictDataRep.Change<SysDictType>().AsQueryable().Where(u => u.Id == dictTypeId).FirstAsync();
			Remove(dictType);

			await _sysDictDataRep.DeleteAsync(u => u.DictTypeId == dictTypeId);
		}

		/// <summary>
		/// 通过字典数据Value查询显示文本Label
		/// 适用于列表中根据字典数据值找文本的子查询 _sysDictDataService.MapDictValueToLabel(() =>obj.Type, "org_type",obj);
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="mappingFiled"></param>
		/// <param name="dictTypeCode"></param>
		/// <param name="parameter"></param>
		/// <returns></returns>
		public string MapDictValueToLabel<T>(Expression<Func<object>> mappingFiled, string dictTypeCode, T parameter)
		{
			return _sysDictDataRep.AsQueryable().InnerJoin<SysDictType>((d, dt) => d.DictTypeId.Equals(dt.Id) && dt.Code == dictTypeCode)
				.SetContext(d => d.Value, mappingFiled, parameter).FirstOrDefault()?.Label;
		}

		/// <summary>
		/// 通过字典数据显示文本Label查询Value
		/// 适用于列表数据导入根据字典数据文本找值的子查询 _sysDictDataService.MapDictLabelToValue(() => obj.Type, "org_type",obj);
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="mappingFiled"></param>
		/// <param name="dictTypeCode"></param>
		/// <param name="parameter"></param>
		/// <returns></returns>
		public string MapDictLabelToValue<T>(Expression<Func<object>> mappingFiled, string dictTypeCode, T parameter)
		{
			return _sysDictDataRep.AsQueryable().InnerJoin<SysDictType>((d, dt) => d.DictTypeId.Equals(dt.Id) && dt.Code == dictTypeCode)
				.SetContext(d => d.Label, mappingFiled, parameter).FirstOrDefault()?.Value;
		}

		/// <summary>
		/// 清理字典数据缓存
		/// </summary>
		/// <param name="dictType"></param>
		private void Remove(SysDictType dictType)
		{
			_sysCacheService.Remove($"{CacheConst.KeyDict}{dictType?.Code}");
			_sysCacheService.Remove($"{CacheConst.KeyTenantDict}{_userManager}:{dictType?.Code}");
		}
	}
}
